package com.mcp.converter.domain.rule.compatibility.function;

import com.mcp.converter.domain.checker.IncompatibilityDetail;
import com.mcp.converter.shared.response.sql.SQLElement;
import com.mcp.converter.domain.rule.compatibility.AbstractFunctionRule;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * 字符串函数兼容性规则
 * OceanBase中许多字符串函数与Oracle不兼容或不支持
 *
 * @author zengxiong
 */
public class StringFunctionRule extends AbstractFunctionRule {

    private static final String RULE_ID = "FN012";
    private static final String RULE_NAME = "字符串函数兼容性";
    private static final String RULE_DESCRIPTION = "OceanBase中许多字符串函数与Oracle不兼容或不支持";

    private static final Set<String> INCOMPATIBLE_STRING_FUNCTIONS = new HashSet<>(Arrays.asList(
            "BFILENAME", "BIN_TO_NUM", "COMPOSE", "DECOMPOSE", "FROM_BASE64", "FROM_XMLTYPE",
            "LCASE", "LCHR", "LENGTHB", "LENGTHC", "LENGTH2", "LENGTH4", "LOADXML", "MAKE_REF", "MULTISET", "NCHR",
            "NLS_CHARSET_DECL_LEN", "NLS_CHARSET_STR", "NLS_INITCAP",
            "NLS_LOWER2", "NLS_SORT", "NLS_UPPER2", "NSL_FIRST_DAY_OF_GLOBAL_WEEK", "OCTET_LENGTH", "REPLICATE",
            "REVERSE", "SOUNDEX", "SOYV", "STRAGG", "SYS_XMLAGG", "UMLEAD", "VALIDATE_CONVERSION", "VERSION_COMPATIBILITY", 
            "WEEK_OF_ISO_YEAR", "WEIGHT_STRING", "WRITE_CLOB_LOCATOR"));

    public StringFunctionRule() {
        super(RULE_ID, RULE_NAME, RULE_DESCRIPTION);

        StringBuilder reasonBuilder = new StringBuilder("OceanBase中不支持的字符串函数：\n");
        StringBuilder impactBuilder = new StringBuilder("可能导致：\n");
        StringBuilder suggestionBuilder = new StringBuilder("建议：\n");

        // 基础字符串函数
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "BFILENAME", "文件路径处理机制不同", "文件操作失败",
                "使用应用层文件路径处理");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "BIN_TO_NUM", "二进制转换算法不同", "数据转换错误",
                "使用标准SQL二进制转换函数");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "COMPOSE", "Unicode合成算法不同", "字符处理错误",
                "使用应用层Unicode处理");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "DECOMPOSE", "Unicode分解算法不同", "字符处理错误",
                "使用应用层Unicode处理");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "FROM_BASE64", "Base64解码算法不同", "数据解码错误",
                "使用标准Base64解码函数");

        // 字符集与国际化函数
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "NLS_CHARSET_DECL_LEN", "字符集声明长度计算不同",
                "字符集转换错误", "统一使用UTF-8字符集");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "NLS_CHARSET_STR", "字符集字符串处理不同", "字符集标识错误",
                "使用系统级字符集管理");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "NLS_INITCAP", "首字母大写规则不同", "字符格式化错误",
                "使用应用层字符格式化");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "NLS_LOWER2", "小写转换规则不同", "字符转换错误",
                "使用标准LOWER函数");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "NLS_SORT", "排序规则不同", "排序结果异常",
                "使用标准ORDER BY子句");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "NLS_UPPER2", "大写转换规则不同", "字符转换错误",
                "使用标准UPPER函数");

        // XML处理函数
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "FROM_XMLTYPE", "XML解析机制不同", "XML处理失败",
                "使用专用XML解析库");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "SYS_XMLAGG", "XML聚合函数不支持", "数据聚合异常",
                "在应用层实现XML聚合逻辑");

        // 长度和字符处理函数
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "LENGTHB", "字节长度计算不同", "长度计算错误",
                "使用标准LENGTH函数");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "LENGTHC", "字符长度计算不同", "长度计算错误",
                "使用标准LENGTH函数");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "LENGTH2", "双字节长度计算不同", "长度计算错误",
                "使用标准LENGTH函数");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "LENGTH4", "四字节长度计算不同", "长度计算错误",
                "使用标准LENGTH函数");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "OCTET_LENGTH", "八位字节长度计算不同", "长度计算错误",
                "使用标准LENGTH函数");

        // 其他字符串函数
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "LCASE", "小写转换函数不支持", "字符转换失败",
                "使用标准LOWER函数");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "LCHR", "字符转换函数不支持", "字符转换失败",
                "使用标准CHR函数");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "LOADXML", "XML加载函数不支持", "XML处理失败",
                "使用专用XML处理库");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "MAKE_REF", "引用创建函数不支持", "引用操作失败",
                "重构避免使用引用");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "MULTISET", "多重集合函数不支持", "集合操作失败",
                "在应用层实现集合操作");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "NCHR", "Unicode字符函数不支持", "字符转换失败",
                "使用标准CHR函数");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "REPLICATE", "字符串复制函数不支持", "字符串操作失败",
                "使用REPEAT函数替代");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "REVERSE", "字符串反转函数不支持", "字符串操作失败",
                "在应用层实现字符串反转");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "SOUNDEX", "语音匹配函数不支持", "模糊匹配失败",
                "使用LIKE操作符替代");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "STRAGG", "字符串聚合函数不支持", "数据聚合异常",
                "使用GROUP_CONCAT函数替代");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "UMLEAD", "Unicode处理函数不支持", "字符处理失败",
                "在应用层实现Unicode处理");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "VALIDATE_CONVERSION", "转换验证机制不同", "数据验证失败",
                "在应用层实现验证逻辑");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "VERSION_COMPATIBILITY", "版本兼容性函数不支持", "版本检查失败",
                "移除版本检查逻辑");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "WEEK_OF_ISO_YEAR", "ISO周函数不支持", "日期计算错误",
                "使用标准日期函数");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "WEIGHT_STRING", "权重字符串函数不支持", "排序权重计算失败",
                "在应用层实现权重计算");
        addFunctionInfo(reasonBuilder, impactBuilder, suggestionBuilder, "WRITE_CLOB_LOCATOR", "CLOB定位器写入不支持", "大对象操作失败",
                "使用标准CLOB操作");

        setIncompatibilityDetail(reasonBuilder.toString(), impactBuilder.toString(), suggestionBuilder.toString(),
                IncompatibilityDetail.Severity.HIGH);
    }

    private void addFunctionInfo(StringBuilder reasonBuilder, StringBuilder impactBuilder,
                                 StringBuilder suggestionBuilder, String functionName, String reason, String impact,
                                 String suggestion) {
        reasonBuilder.append(" - ").append(functionName).append(": ").append(reason).append("\n");
        impactBuilder.append(" - ").append(functionName).append(": ").append(impact).append("\n");
        suggestionBuilder.append(" - ").append(functionName).append(": ").append(suggestion).append("\n");
    }

    @Override
    public boolean matches(Object target) {
        if (target instanceof SQLElement) {
            SQLElement element = (SQLElement) target;
            if (isFunctionElement(element)) {
                String functionName = element.getName().toUpperCase();
                return INCOMPATIBLE_STRING_FUNCTIONS.contains(functionName);
            }
        }
        return false;
    }
    
    @Override
    public Set<String> getIncompatibleFunctions() {
        return new HashSet<>(INCOMPATIBLE_STRING_FUNCTIONS);
    }
}